/**
 * 
 */
package com.geekteam.masterenglish.provider;

import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.net.Uri;

import com.geekteam.masterenglish.provider.EEContract.Album;
import com.geekteam.masterenglish.provider.EEContract.Lession;
import com.geekteam.masterenglish.provider.EEDatabase.Tables;
import com.geekteam.masterenglish.utils.LogUtils;
import com.geekteam.masterenglish.utils.SelectionBuilder;

/**
 * @author MTROL
 *
 */
public class EEProvider extends ContentProvider{
	private static final String TAG = LogUtils.makeLogTag(EEProvider.class);
	
	private EEDatabase mOpenHelper;
	private static final int LESSION = 100;
	private static final int LESSION_ID = 101;
	private static final int LESSION_IN_ALBUM = 102;
	
	private static final int ALBUM = 200;
	private static final int ALBUM_IN_BOOK = 201;
	
	private static final UriMatcher sUriMatcher = buildUriMatcher();
	
	private static UriMatcher buildUriMatcher() {
		final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
		final String authority = EEContract.CONTENT_AUTHORITY;
		
		matcher.addURI(authority, "lessions", LESSION);
		matcher.addURI(authority, "lessions/type/*", LESSION_IN_ALBUM);
		matcher.addURI(authority, "lessions/*", LESSION_ID);
		
		matcher.addURI(authority, "albums", ALBUM);
		matcher.addURI(authority, "albums/book/*", ALBUM_IN_BOOK);
		
		return matcher;
	}
	
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		if (uri == EEContract.BASE_CONTENT_URI) {
			deleteDatabase();
			getContext().getContentResolver().notifyChange(uri, null, false);
			return 1;
		}
		try {
			final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
			final SelectionBuilder builder = buildSimpleSelection(uri);
			int retVal = builder.where(selection, selectionArgs).delete(db);
			getContext().getContentResolver().notifyChange(uri, null);
			return retVal;
		} catch (SQLiteException ex) {
			LogUtils.LOGE(TAG, "delete error: "+ex.getMessage());
			return -1;
		}
	}

	@Override
	public String getType(Uri uri) {
		final int match = sUriMatcher.match(uri);
		switch(match){
		case LESSION:
			return Lession.CONTENT_TYPE;
		case LESSION_ID:
			return Lession.CONTENT_ITEM_TYPE;
		case LESSION_IN_ALBUM:
			return Lession.CONTENT_TYPE;
		case ALBUM:
			return Album.CONTENT_TYPE;
		case ALBUM_IN_BOOK:
			return Album.CONTENT_TYPE;
		default:
			throw new UnsupportedOperationException("Unknown uri: " + uri);
		}
	}
	
	private void deleteDatabase() {
		mOpenHelper.close();
		Context context = getContext();
		EEDatabase.deleteDatabase(context);
		mOpenHelper = new EEDatabase(getContext());
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		final int match = sUriMatcher.match(uri);
		switch (match) {
		case LESSION:
			db.insertOrThrow(Tables.LESSIONS, null, values);
			getContext().getContentResolver().notifyChange(uri, null);
			return Lession.buildLessionId(values.getAsString(Lession.ID));
		case ALBUM:
			db.insertOrThrow(Tables.ALBUMS, null, values);
			getContext().getContentResolver().notifyChange(uri, null);
			return Album.buildAlbumId(values.getAsString(Album.ID));
		}
		return null;
	}

	@Override
	public boolean onCreate() {
		mOpenHelper = new EEDatabase(getContext());
		mOpenHelper.getWritableDatabase();
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		final SQLiteDatabase db = mOpenHelper.getReadableDatabase();

		final int match = sUriMatcher.match(uri);
		Cursor cursor;
		switch (match) {
		default:
			final SelectionBuilder builder = buildExpandedSelection(uri, match);
			cursor = builder.where(selection, selectionArgs).query(db,
					projection, sortOrder);
			cursor.setNotificationUri(getContext().getContentResolver(), uri);
			return cursor;
		}
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		LogUtils.LOGV(TAG,
				"update(uri=" + uri + ", values=" + values.toString() + ")");
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		final SelectionBuilder builder = buildSimpleSelection(uri);
		int retVal = builder.where(selection, selectionArgs).update(db, values);
		getContext().getContentResolver().notifyChange(uri, null);
		return retVal;
	}
	
	@SuppressLint("NewApi")
	@Override
	public ContentProviderResult[] applyBatch(
			ArrayList<ContentProviderOperation> operations)
			throws OperationApplicationException {
		final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		db.beginTransaction();
		try {
			final int numOperations = operations.size();
			final ContentProviderResult[] results = new ContentProviderResult[numOperations];
			for (int i = 0; i < numOperations; i++) {
				results[i] = operations.get(i).apply(this, results, i);
			}
			db.setTransactionSuccessful();
			return results;
		} catch (SQLiteException ex) {
			return null;
		} finally {
			LogUtils.LOGI(TAG, "finally running");
			if (db.inTransaction()) {
				try {
					db.endTransaction();
				} catch (SQLiteException ex) {
					ex.printStackTrace();
				}
			}
			db.close();
		}
	}

	private SelectionBuilder buildExpandedSelection(Uri uri, int match) {
		final SelectionBuilder builder = new SelectionBuilder();
		switch (match) {
		case LESSION:
			return builder.table(Tables.LESSIONS);
		case LESSION_ID:
			String lessionId = Lession.getLessionId(uri);
			return builder.table(Tables.LESSIONS).where(Lession.ID+"=?", lessionId);
		case LESSION_IN_ALBUM:
			String lessionType = Lession.getLessionType(uri);
			return builder.table(Tables.LESSIONS).where(Lession.ALBUM_ID+"=?", lessionType);
		case ALBUM:
			return builder.table(Tables.ALBUMS);
		case ALBUM_IN_BOOK:
			String bookId = Album.getBookId(uri);
			return builder.table(Tables.ALBUMS).where(Album.BOOK_ID+"=?", bookId);
		default:
			throw new UnsupportedOperationException("Unknown uri: " + uri);
		}
	}
	
	private SelectionBuilder buildSimpleSelection(Uri uri){
		final SelectionBuilder builder = new SelectionBuilder();
		final int match = sUriMatcher.match(uri);
		switch (match) {
		case LESSION:
			return builder.table(Tables.LESSIONS);
		case LESSION_ID:
			String lessionId = Lession.getLessionId(uri);
			return builder.table(Tables.LESSIONS).where(Lession.ID+"=?", lessionId);
		case LESSION_IN_ALBUM:
			String lessionType = Lession.getLessionType(uri);
			return builder.table(Tables.LESSIONS).where(Lession.ALBUM_ID+"=?", lessionType);
		case ALBUM:
			return builder.table(Tables.ALBUMS);
		case ALBUM_IN_BOOK:
			String bookId = Album.getBookId(uri);
			return builder.table(Tables.ALBUMS).where(Album.BOOK_ID+"=?", bookId);
		default:
			throw new UnsupportedOperationException("Unknown uri: " + uri);
		}
	}
}
